package com.hsu.hsurpc.utils;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.resource.ClassPathResource;
import cn.hutool.setting.dialect.Props;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.Properties;

/**
 * Properties 配置文件读取工具类
 * @Author Hsu琛君珩
 * @Date 2024-09-18 14:52
 * @Description
 * @Version: v1.0.0
 */
public class PropertiesConfigUtils {

    /**
     * 从 properties 文件加载配置并映射为指定的 Java 对象
     *
     * @param fileName 配置文件名
     * @param tClass   目标类类型
     * @param charset  指定编码
     * @param <T>      泛型
     * @return 映射的配置文件对象
     */
    public static <T> T loadPropertiesConfig(String fileName, Class<T> tClass, Charset charset) {
        ClassPathResource resource = new ClassPathResource(fileName);
        try (InputStream inputStream = resource.getStream()) {
            // 创建 Properties 对象并加载流内容，指定编码
            Properties properties = new Properties();
            properties.load(new java.io.InputStreamReader(inputStream, charset)); // 使用正确的编码读取
            // 将 Properties 转换为 Props 对象
            Props props = new Props();
            props.putAll(properties);
            // 映射到配置对象
            return mapToConfigObject(props, tClass);
        } catch (Exception e) {
            throw new RuntimeException("加载 Properties 文件失败: " + fileName, e);
        }
    }

    /**
     * 将 Props 文件中的键值映射到配置对象中
     *
     * @param props 配置文件
     * @param tClass 目标类类型
     * @param <T> 泛型
     * @return 映射后的配置对象
     */
    private static <T> T mapToConfigObject(Props props, Class<T> tClass) {
        try {
            // 创建目标类的实例
            T configInstance = tClass.getDeclaredConstructor().newInstance();

            // 遍历目标类的字段，将 .properties 中的键值对设置到对应字段
            for (Field field : tClass.getDeclaredFields()) {
                String key = "rpc." + field.getName(); // 根据字段名构造 key，例如 "rpc.name"
                String value = props.getStr(key); // 获取配置文件中的值

                if (value != null) {
                    // 如果字段是 Integer 类型，进行类型转换
                    if (field.getType().equals(Integer.class)) {
                        field.setAccessible(true); // 允许访问私有字段
                        field.set(configInstance, Integer.parseInt(value));
                    }
                    // 如果字段是 Boolean 类型，进行类型转换
                    else if (field.getType().equals(Boolean.class)) {
                        field.setAccessible(true);
                        field.set(configInstance, Boolean.parseBoolean(value));
                    }
                    // 处理其他类型（如 String）
                    else {
                        field.setAccessible(true);
                        field.set(configInstance, value);
                    }
                }
            }
            return configInstance; // 返回配置对象
        } catch (Exception e) {
            throw new RuntimeException("加载 Properties 文件到配置对象失败: " + e.getMessage(), e);
        }
    }
}
